package cn.org.xuanguang.kepler.hormos.rdb.plugin.mysql;

import cn.org.xuanguang.kepler.hormos.rdb.dml.operator.delete.DeleteOperatorParameter;
import cn.org.xuanguang.kepler.hormos.rdb.dml.operator.insert.InsertOperatorParameter;
import cn.org.xuanguang.kepler.hormos.rdb.dml.operator.select.SelectOperatorParameter;
import cn.org.xuanguang.kepler.hormos.rdb.dml.operator.update.UpdateOperatorParameter;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.param.Term;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.param.TermType;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.sql.PrepareSqlFragments;
import cn.org.xuanguang.kepler.hormos.rdb.dsl.sql.SqlRequest;
import cn.org.xuanguang.kepler.hormos.rdb.plugin.DmlSQLBuilder;
import cn.org.xuanguang.kepler.hormos.rdb.plugin.TermTypeUtils;

import java.util.Arrays;
import java.util.Collections;

/**
 * mysql sql 构建
 */
public class MysqlDmlSQLBuilder implements DmlSQLBuilder {

    public MysqlDmlSQLBuilder() {
    }

    public static DmlSQLBuilder of() {
        return new MysqlDmlSQLBuilder();
    }

    @Override
    public SqlRequest buildDelete(DeleteOperatorParameter parameter) {

        PrepareSqlFragments fragments = PrepareSqlFragments.of();


        fragments.addSql("DELETE FROM ");
        if (parameter.getTableName() != null) {
            fragments.addSql(parameter.getTableName());
        }
        if (parameter.getTerms() != null && !parameter.getTerms().isEmpty()) {
            fragments.addSql(" WHERE ");
            PrepareSqlFragments termFragments = PrepareSqlFragments.of();
            parameter.getTerms().forEach(term -> {

                if (term.getType() == Term.Type.and) {
                    termFragments.addSql(" AND ");
                } else if (term.getType() == Term.Type.or) {
                    termFragments.addSql(" OR ");
                }
                termFragments.addSql(term.getColumn() + " " + TermTypeUtils.getTermType(term.getTermType()) + " ? ");
                termFragments.addParameter(Collections.singletonList(term.getValue()));

            });
            // 去掉where 后的第一个and或者or
            termFragments.removeFirstSql();
            fragments.addFragments(termFragments);
        }

        return fragments.toRequest();
    }


    @Override
    public SqlRequest buildInsert(InsertOperatorParameter parameter) {

        PrepareSqlFragments fragments = PrepareSqlFragments.of();

        PrepareSqlFragments intoSql = PrepareSqlFragments.of();
        PrepareSqlFragments valuesSql = PrepareSqlFragments.of();

        fragments.addSql("INSERT INTO ");
        if (parameter.getTableName() != null) {
            fragments.addSql(parameter.getTableName());
        }
        // 插入字段
        intoSql.addSql("(");
        parameter.getColumns().forEach(column -> {
            intoSql.addSql(column);
            intoSql.addSql(",");
        });
        intoSql.removeLastSql();
        intoSql.addSql(")");


        valuesSql.addSql(" VALUES(");
        parameter.getValues().forEach(value -> {
            valuesSql.addSql("?");
            valuesSql.addParameter(Collections.singletonList(value));
            valuesSql.addSql(",");
        });
        valuesSql.removeLastSql();
        valuesSql.addSql(")");

        fragments.addFragments(intoSql);
        fragments.addFragments(valuesSql);


        return fragments.toRequest();
    }

    @Override
    public SqlRequest buildUpdate(UpdateOperatorParameter parameter) {
        /*
         *  UPDATE table_name
         *  SET column1 = value1, column2 = value2, ...
         *  WHERE condition;
         */
        PrepareSqlFragments fragments = PrepareSqlFragments.of();
        fragments.addSql("UPDATE ");
        if (parameter.getTableName() != null) {
            fragments.addSql(parameter.getTableName());
        }
        if (parameter.getColumns() != null && !parameter.getColumns().isEmpty()) {
            fragments.addSql(" SET ");
            parameter.getColumns().forEach(column -> {
                fragments.addSql(column);
                fragments.addSql(" = ?");
                fragments.addParameter(Collections.singletonList(parameter.getValues().get(parameter.getColumns().indexOf(column))));
                fragments.addSql(" ,");
            });
            fragments.removeLastSql();
        }
        if (parameter.getTerms() != null && !parameter.getTerms().isEmpty()) {
            fragments.addSql(" WHERE ");
            PrepareSqlFragments termFragments = PrepareSqlFragments.of();
            parameter.getTerms().forEach(term -> {

                if (term.getType() == Term.Type.and) {
                    termFragments.addSql(" AND ");
                } else if (term.getType() == Term.Type.or) {
                    termFragments.addSql(" OR ");
                }
                termFragments.addSql(term.getColumn() + " " + TermTypeUtils.getTermType(term.getTermType()) + " ? ");
                termFragments.addParameter(Collections.singletonList(term.getValue()));

            });
            // 去掉where 后的第一个and或者or
            termFragments.removeFirstSql();
            fragments.addFragments(termFragments);
        }

        return fragments.toRequest();
    }

    @Override
    public SqlRequest buildSelect(SelectOperatorParameter parameter) {
        /*
         *  SELECT column1, column2, ...
         *  FROM table_name
         *  WHERE condition;
         */
        PrepareSqlFragments fragments = PrepareSqlFragments.of();
        if (parameter.getColumns() != null && !parameter.getColumns().isEmpty()) {
            fragments.addSql("SELECT ");
            parameter.getColumns().forEach(column -> {
                fragments.addSql(column);
                fragments.addSql(",");
            });
            fragments.removeLastSql();
        }
        if (parameter.getTableName() != null) {
            fragments.addSql(" FROM ");
            fragments.addSql(parameter.getTableName());
        }
        if (parameter.getTerms() != null && !parameter.getTerms().isEmpty()) {
            fragments.addSql(" WHERE ");
            //单独弄出来查询条件拼装
            PrepareSqlFragments whereFragments = PrepareSqlFragments.of();
            parameter.getTerms().forEach(term -> {
                if (term.getType() == Term.Type.and) {
                    whereFragments.addSql(" AND ");
                } else if (term.getType() == Term.Type.or) {
                    whereFragments.addSql(" OR ");
                }
                if (term.getTermType().equals(TermType.in)) {
                    // in
                    if (term.getValue() instanceof Object[]) {
                        Object[] values = (Object[]) term.getValue();
                        int size = values.length;
                        String[] arr = new String[size];
                        //去掉最后一个逗号
//                        Arrays.fill(arr, "?,");
//


                        whereFragments.addSql(term.getColumn())
                                .addSql(" in ")
                                .addSql("(");
                        for (int i = 0; i < arr.length; i++) {
                            if (i == arr.length - 1) {
                                arr[i] = "?";
                            } else {
                                arr[i] = "?,";
                            }
                            whereFragments.addSql(arr[i]);
                        }
                        whereFragments.addSql(")")
                                .addParameter(values);
                    }
                } else if (term.getTermType().equals(TermType.nin)) {
//                    not in
                    if (term.getValue() instanceof Object[]) {
                        Object[] values = (Object[]) term.getValue();
                        int size = values.length;
                        String[] arr = new String[size];
                        Arrays.fill(arr, "?");
                        whereFragments.addSql(term.getColumn())
                                .addSql(" not in ")
                                .addSql("(");
                        for (int i = 0; i < arr.length; i++) {
                            if (i == arr.length - 1) {
                                arr[i] = "?";
                            } else {
                                arr[i] = "?,";
                            }
                            whereFragments.addSql(arr[i]);
                        }
                        whereFragments.addSql(")")
                                .addParameter(values);
                    }
                } else {
                    whereFragments.addSql(term.getColumn() + " " + TermTypeUtils.getTermType(term.getTermType()) + " ? ");
                    whereFragments.addParameter(Collections.singletonList(term.getValue()));
                    whereFragments.addSql(" ");
                }


            });
            whereFragments.removeFirstSql();
            fragments.addFragments(whereFragments);
        }
        return fragments.toRequest();
    }
}
